热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

科科|搜索关键词_基于webmagic的爬虫小应用爬取知乎用户信息

篇首语:本文由编程笔记#小编为大家整理,主要介绍了基于webmagic的爬虫小应用--爬取知乎用户信息相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了基于webmagic的爬虫小应用--爬取知乎用户信息相关的知识,希望对你有一定的参考价值。






最近跟舍友@小疯一起研究爬虫
他写了个小应用-CSDN博客爬虫 有兴趣的朋友可以点进去看看哦~
一起学习。
一起进步。
想要源代码的朋友点击这里下载哦~


听到“爬虫”,是不是第一时间想到python/php ? 多少想玩爬虫的java学习者就因为语言不通而止步。Java是真的不能做爬虫吗?
当然不是。
只不过python的3行代码能解决的问题,而Java要30行。

这里推荐大家一个大牛做的java爬虫框架 【WebMagic】
文档简单易懂!java爬虫开发的福利啊!
一起来动手做一个小应用吧!




爬虫小应用–知乎用户信息

爬虫思想有3步
1. 抽取目标链接
2. 抽取需要的信息
3. 处理数据

一、 抽取目标链接 (确定入口地址,这里的入口是https://www.zhihu.com/search?type=people&q=java)

接下来查看html结构,确定待爬取的目标链接。(这里我的目标链接是【前10个用户的详细信息页面的url】)

二、抽取需要的信息(webmagic提供了3种方式,xpath,css选择,正则表达式。具体可以查看下[WebMagic文档](http://webmagic.io/docs/zh/))

确定好【目标的信息】,如下图。

创建对应的实体对象

package entity;
/**
* 知乎用户信息
* @author antgan
*
*/

public class ZhihuUser
private String key;//keyword
private String name;//用户名
private String identity;//身份
private String location;//所在地
private String profession;//行业
private int sex;//性别
private String school;//学校
private String major;//专业
private String recommend;//个人简介
private String picUrl;//头像url
private int agree;//赞同
private int thanks;//感谢
private int ask;//提问数
private int answer;//回答数
private int article;//文章数
private int collection;//收藏数
public String getKey()
return key;

public void setKey(String key)
this.key = key;

public String getName()
return name;

public void setName(String name)
this.name = name;

public String getIdentity()
return identity;

public void setIdentity(String identity)
this.identity = identity;

public String getLocation()
return location;

public void setLocation(String location)
this.location = location;

public String getProfession()
return profession;

public void setProfession(String profession)
this.profession = profession;

public int getSex()
return sex;

public void setSex(int sex)
this.sex = sex;

public String getSchool()
return school;

public void setSchool(String school)
this.school = school;

public String getMajor()
return major;

public void setMajor(String major)
this.major = major;

public String getRecommend()
return recommend;

public void setRecommend(String recommend)
this.recommend = recommend;

public String getPicUrl()
return picUrl;

public void setPicUrl(String picUrl)
this.picUrl = picUrl;

public int getAgree()
return agree;

public void setAgree(int agree)
this.agree = agree;

public int getThanks()
return thanks;

public void setThanks(int thanks)
this.thanks = thanks;

public int getAsk()
return ask;

public void setAsk(int ask)
this.ask = ask;

public int getAnswer()
return answer;

public void setAnswer(int answer)
this.answer = answer;

public int getArticle()
return article;

public void setArticle(int article)
this.article = article;

public int getCollection()
return collection;

public void setCollection(int collection)
this.collection = collection;

@Override
public String toString()
return "ZhihuUser [name=" + name + ", identity=" + identity + ", location=" + location + ", profession="
+ profession + ", sex=" + sex + ", school=" + school + ", major=" + major + ", recommend=" + recommend
+ ", picUrl=" + picUrl + ", agree=" + agree + ", thanks=" + thanks + ", ask=" + ask + ", answer="
+ answer + ", article=" + article + ", collection=" + collection + "]";

编写PageProcessor(Processor中的process方法是webmagic的核心,负责抽取目标url的逻辑)

package repo;
import dao.ZhihuDao;
import dao.impl.ZhihuDaoImpl;
import entity.ZhihuUser;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;
/**
* 知乎用户小爬虫

* 输入搜索用户关键词(keyword),并把搜出来的用户信息爬出来

* @date 2016-5-3
* @website ghb.soecode.com
* @csdn blog.csdn.net/antgan
* @author antgan
*
*/

public class ZhiHuUserPageProcessor implements PageProcessor
//抓取网站的相关配置,包括:编码、抓取间隔、重试次数等
private Site site = Site.me().setRetryTimes(10).setSleepTime(1000);
//用户数量
private static int num = 0;
//搜索关键词
private static String keyword = "JAVA";
//数据库持久化对象,用于将用户信息存入数据库
private ZhihuDao zhihuDao = new ZhihuDaoImpl();
/**
* process 方法是webmagic爬虫的核心

* 编写抽取【待爬取目标链接】的逻辑代码在html中。
*/

@Override
public void process(Page page)
//1. 如果是用户列表页面 【入口页面】,将所有用户的详细页面的url放入target集合中。
if(page.getUrl().regex("https://www\\\\.zhihu\\\\.com/search\\\\?type=people&q=[\\\\s\\\\S]+").match())
page.addTargetRequests(page.getHtml().xpath("//ul[@class='list users']/li/div/div[@class='body']/div[@class='line']").links().all());

//2. 如果是用户详细页面
else
num++;//用户数++
/*实例化ZhihuUser,方便持久化存储。*/
ZhihuUser user = new ZhihuUser();
/*从下载到的用户详细页面中抽取想要的信息,这里使用xpath居多*/
/*为了方便理解,抽取到的信息先用变量存储,下面再赋值给对象*/
String name = page.getHtml().xpath("//div[@class='title-section ellipsis']/span[@class='name']/text()").get();
String identity = page.getHtml().xpath("//div[@class='title-section ellipsis']/span[@class='bio']/@title").get();
String location = page.getHtml().xpath("//div[@class='item editable-group']/span[@class='info-wrap']/span[@class='location item']/@title").get();
String profession = page.getHtml().xpath("//div[@class='item editable-group']/span[@class='info-wrap']/span[@class='business item']/@title").get();
boolean isMale = page.getHtml().xpath("//span[@class='item gender']/i[@class='icon icon-profile-male']").match();
boolean isFemale = page.getHtml().xpath("//span[@class='item gender']/i[@class='icon icon-profile-female']").match();
int sex = -1;
/*因为知乎有一部分人不设置性别 或者 不显示性别。所以需要判断一下。*/
if(isMale&&!isFemale) sex=1;//1代表男性
else if(!isMale&&isFemale) sex=0;//0代表女性
else sex=2;//2代表未知
String school = page.getHtml().xpath("//span[@class='education item']/@title").get();
String major = page.getHtml().xpath("//span[@class='education-extra item']/@title").get();
String recommend = page.getHtml().xpath("//span[@class='fold-item']/span[@class='content']/@title").get();
String picUrl = page.getHtml().xpath("//div[@class='body clearfix']/img[@class='Avatar Avatar--l']/@src").get();
int agree = Integer.parseInt(page.getHtml().xpath("//span[@class='zm-profile-header-user-agree']/strong/text()").get());
int thanks = Integer.parseInt(page.getHtml().xpath("//span[@class='zm-profile-header-user-thanks']/strong/text()").get());
int ask = Integer.parseInt(page.getHtml().xpath("//div[@class='profile-navbar clearfix']/a[2]/span[@class='num']/text()").get());
int answer = Integer.parseInt(page.getHtml().xpath("//div[@class='profile-navbar clearfix']/a[3]/span[@class='num']/text()").get());
int article = Integer.parseInt(page.getHtml().xpath("//div[@class='profile-navbar clearfix']/a[4]/span[@class='num']/text()").get());
int collection = Integer.parseInt(page.getHtml().xpath("//div[@class='profile-navbar clearfix']/a[5]/span[@class='num']/text()").get());
//对象赋值
user.setKey(keyword);
user.setName(name);
user.setIdentity(identity);
user.setLocation(location);
user.setProfession(profession);
user.setSex(sex);
user.setSchool(school);
user.setMajor(major);
user.setRecommend(recommend);
user.setPicUrl(picUrl);
user.setAgree(agree);
user.setThanks(thanks);
user.setAsk(ask);
user.setAnswer(answer);
user.setArticle(article);
user.setCollection(collection);
System.out.println("num:"+num +" " + user.toString());//输出对象
zhihuDao.saveUser(user);//保存用户信息到数据库


@Override
public Site getSite()
return this.site;

public static void main(String[] args)
long startTime ,endTime;
System.out.println("========知乎用户信息小爬虫【启动】喽!=========");
startTime = new Date().getTime();
//入口为:【https://www.zhihu.com/search?type=people&q=xxx 】,其中xxx 是搜索关键词
Spider.create(new ZhiHuUserPageProcessor()).addUrl("https://www.zhihu.com/search?type=people&q="+keyword).thread(5).run();
endTime = new Date().getTime();
System.out.println("========知乎用户信息小爬虫【结束】喽!=========");
System.out.println("一共爬到"+num+"个用户信息!用时为:"+(endTime-startTime)/1000+"s");

三、处理数据 (这里我存储在本地数据库中)

Dao层接口

package dao;
import entity.ZhihuUser;
/**
* 知乎 数据持久化 接口
* @author 甘海彬
*
*/

public interface ZhihuDao
/**
* 保存用户信息
* @param user
* @return
*/

public int saveUser(ZhihuUser user);

Dao实现类

package dao.impl;
import java.util.ArrayList;
import java.util.List;
import dao.ZhihuDao;
import entity.ZhihuUser;
import util.DBHelper;
/**
* 知乎 数据库持久化接口 实现
* @author 甘海彬
*
*/

public class ZhihuDaoImpl implements ZhihuDao
@Override
public int saveUser(ZhihuUser user)
DBHelper dbhelper = new DBHelper();
StringBuffer sql = new StringBuffer();
sql.append("INSERT INTO spider_zhihu_user ( `key`,`name`,identity,location,profession,sex,school,major,recommend,picUrl,agree,thanks,ask,answer,article,collection)")
//`key`,`name`,identity,location,profession,sex,school,major,recommend,picUrl,agree,thanks,ask,answer,article,collection
.append("VALUES (? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? ) ");
//设置 sql values 的值
List sqlValues &#61; new ArrayList<>();
sqlValues.add(user.getKey());
sqlValues.add(user.getName());
sqlValues.add(user.getIdentity());
sqlValues.add(user.getLocation());
sqlValues.add(user.getProfession());
sqlValues.add(""&#43;user.getSex());
sqlValues.add(user.getSchool());
sqlValues.add(user.getMajor());
sqlValues.add(user.getRecommend());
sqlValues.add(user.getPicUrl());
sqlValues.add(""&#43;user.getAgree());
sqlValues.add(""&#43;user.getThanks());
sqlValues.add(""&#43;user.getAsk());
sqlValues.add(""&#43;user.getAnswer());
sqlValues.add(""&#43;user.getArticle());
sqlValues.add(""&#43;user.getCollection());
try
int result &#61; dbhelper.executeUpdate(sql.toString(),sqlValues);
catch(Exception e)
finally
dbhelper.close();

return result;

这里我封装了个DbHelpler类&#xff0c;方便进行持久化操作&#xff0c;使用单例模式&#xff0c;并线程同步。

package util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
/**
* JDBC通用类
* &#64;author GANAB
*
*/

public class DBHelper
public static final String driver_class &#61; "oracle.jdbc.OracleDriver";
public static final String driver_url &#61; "jdbc:oracle:thin:&#64;ita-031-w7:1521:xe";
public static final String user &#61; "abel";
public static final String password &#61; "123";
private static Connection conn &#61; null;
private PreparedStatement pst &#61; null;
private ResultSet rst &#61; null;
public DBHelper()
try
conn &#61; getConnInstance();
catch (Exception e)
e.printStackTrace();


private Connection getConnInstance()
if(conn &#61;&#61; null)
try
Class.forName(driver_class);
conn &#61; DriverManager.getConnection(driver_url, user, password);
catch (ClassNotFoundException e)
e.printStackTrace();
catch (SQLException e)
e.printStackTrace();

System.out.println("Connect success.");

return conn;

public void close()
try
if (pst !&#61; null)
this.pst.close();

if (rst !&#61; null)
this.rst.close();

if (conn !&#61; null)
conn.close();

System.out.println("Close connection success.");
catch (SQLException e)
e.printStackTrace();


/**
* query
*
* &#64;param sql
* &#64;param sqlValues
* &#64;return ResultSet
*/

public ResultSet executeQuery(String sql, List sqlValues)
try
pst &#61; conn.prepareStatement(sql);
if (sqlValues !&#61; null && sqlValues.size() > 0)
setSqlValues(pst, sqlValues);

rst &#61; pst.executeQuery();
catch (SQLException e)
e.printStackTrace();

return rst;

/**
* update
*
* &#64;param sql
* &#64;param sqlValues
* &#64;return result
*/

public int executeUpdate(String sql, List sqlValues)
int result &#61; -1;
try
pst &#61; conn.prepareStatement(sql);
if (sqlValues !&#61; null && sqlValues.size() > 0)
setSqlValues(pst, sqlValues);

result &#61; pst.executeUpdate();
catch (SQLException e)
e.printStackTrace();

return result;

/**
* sql set value
*
* &#64;param pst
* &#64;param sqlValues
*/

private void setSqlValues(PreparedStatement pst, List sqlValues)
for (int i &#61; 0; i try
pst.setObject(i &#43; 1, sqlValues.get(i));
catch (SQLException e)
e.printStackTrace();



噢&#xff01;对了&#xff01;表的创建sql也提供一下&#xff01;

CREATE TABLE &#96;spider_zhihu_user&#96; (
&#96;id&#96; int(11) NOT NULL AUTO_INCREMENT,
&#96;key&#96; varchar(30) DEFAULT NULL,
&#96;name&#96; varchar(30) DEFAULT NULL,
&#96;identity&#96; varchar(100) DEFAULT NULL,
&#96;location&#96; varchar(20) DEFAULT NULL,
&#96;profession&#96; varchar(30) DEFAULT NULL,
&#96;sex&#96; int(2) DEFAULT NULL,
&#96;school&#96; varchar(30) DEFAULT NULL,
&#96;major&#96; varchar(30) DEFAULT NULL,
&#96;recommend&#96; varchar(100) DEFAULT NULL,
&#96;picUrl&#96; varchar(255) DEFAULT NULL,
&#96;agree&#96; int(11) DEFAULT NULL,
&#96;thanks&#96; int(11) DEFAULT NULL,
&#96;ask&#96; int(11) DEFAULT NULL,
&#96;answer&#96; int(11) DEFAULT NULL,
&#96;article&#96; int(11) DEFAULT NULL,
&#96;collection&#96; int(11) DEFAULT NULL,
PRIMARY KEY (&#96;id&#96;)
) ENGINE&#61;InnoDB AUTO_INCREMENT&#61;104 DEFAULT CHARSET&#61;utf8;

以上就是全部代码。

进行测试。


完美~

你知道可以拿这些数据做什么呢&#xff1f;
科科&#xff0c;我也不知道。


推荐阅读
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Java实战之电影在线观看系统的实现
    本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
author-avatar
h40012222
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有